home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / dev / lang / Python16_Src.lha / Python16_Source / Python / dynload_beos.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-08-03  |  6.1 KB  |  252 lines

  1. /* Support for dynamic loading of extension modules */
  2.  
  3. #include <kernel/image.h>
  4. #include <kernel/OS.h>
  5. #include <stdlib.h>
  6. #include <unistd.h>
  7.  
  8. #include "Python.h"
  9. #include "importdl.h"
  10.  
  11. const struct filedescr _PyImport_DynLoadFiletab[] = {
  12.     {".so", "rb", C_EXTENSION},
  13.     {"module.so", "rb", C_EXTENSION},
  14.     {0, 0}
  15. };
  16.  
  17. #if defined(MAXPATHLEN) && !defined(_SYS_PARAM_H)
  18. #undef MAXPATHLEN
  19. #endif
  20.  
  21. #ifdef WITH_THREAD
  22. #include "pythread.h"
  23. static PyThread_type_lock beos_dyn_lock;
  24. #endif
  25.  
  26. static PyObject *beos_dyn_images = NULL;
  27.  
  28. /* ----------------------------------------------------------------------
  29.  * BeOS dynamic loading support
  30.  *
  31.  * This uses shared libraries, but BeOS has its own way of doing things
  32.  * (much easier than dlfnc.h, from the look of things).  We'll use a
  33.  * Python Dictionary object to store the images_ids so we can be very
  34.  * nice and unload them when we exit.
  35.  *
  36.  * Note that this is thread-safe.  Probably irrelevent, because of losing
  37.  * systems... Python probably disables threads while loading modules.
  38.  * Note the use of "probably"!  Better to be safe than sorry. [chrish]
  39.  *
  40.  * As of 1.5.1 this should also work properly when you've configured
  41.  * Python without thread support; the 1.5 version required it, which wasn't
  42.  * very friendly.  Note that I haven't tested it without threading... why
  43.  * would you want to avoid threads on BeOS? [chrish]
  44.  *
  45.  * As of 1.5.2, the PyImport_BeImageID() function has been removed; Donn
  46.  * tells me it's not necessary anymore because of PyCObject_Import().
  47.  * [chrish]
  48.  */
  49.  
  50. /* Whack an item; the item is an image_id in disguise, so we'll call
  51.  * unload_add_on() for it.
  52.  */
  53. static void beos_nuke_dyn( PyObject *item )
  54. {
  55.     status_t retval;
  56.  
  57.     if( item ) {
  58.         image_id id = (image_id)PyInt_AsLong( item );
  59.         
  60.         retval = unload_add_on( id );
  61.     }
  62. }
  63.  
  64. /* atexit() handler that'll call unload_add_on() for every item in the
  65.  * dictionary.
  66.  */
  67. static void beos_cleanup_dyn( void )
  68. {
  69.     if( beos_dyn_images ) {
  70.         int idx;
  71.         int list_size;
  72.         PyObject *id_list;
  73.  
  74. #ifdef WITH_THREAD
  75.         PyThread_acquire_lock( beos_dyn_lock, 1 );
  76. #endif
  77.  
  78.         id_list = PyDict_Values( beos_dyn_images );
  79.  
  80.         list_size = PyList_Size( id_list );
  81.         for( idx = 0; idx < list_size; idx++ ) {
  82.             PyObject *the_item;
  83.             
  84.             the_item = PyList_GetItem( id_list, idx );
  85.             beos_nuke_dyn( the_item );
  86.         }
  87.  
  88.         PyDict_Clear( beos_dyn_images );
  89.  
  90. #ifdef WITH_THREAD
  91.         PyThread_free_lock( beos_dyn_lock );
  92. #endif
  93.     }
  94. }
  95.  
  96. /*
  97.  * Initialize our dictionary, and the dictionary mutex.
  98.  */
  99. static void beos_init_dyn( void )
  100. {
  101.     /* We're protected from a race condition here by the atomic init_count
  102.      * variable.
  103.      */
  104.     static int32 init_count = 0;
  105.     int32 val;
  106.  
  107.     val = atomic_add( &init_count, 1 );
  108.     if( beos_dyn_images == NULL && val == 0 ) {
  109.         beos_dyn_images = PyDict_New();
  110. #ifdef WITH_THREAD
  111.         beos_dyn_lock = PyThread_allocate_lock();
  112. #endif
  113.         atexit( beos_cleanup_dyn );
  114.     }
  115. }
  116.  
  117. /*
  118.  * Add an image_id to the dictionary; the module name of the loaded image
  119.  * is the key.  Note that if the key is already in the dict, we unload
  120.  * that image; this should allow reload() to work on dynamically loaded
  121.  * modules (super-keen!).
  122.  */
  123. static void beos_add_dyn( char *name, image_id id )
  124. {
  125.     int retval;
  126.     PyObject *py_id;
  127.  
  128.     if( beos_dyn_images == NULL ) {
  129.         beos_init_dyn();
  130.     }
  131.  
  132. #ifdef WITH_THREAD
  133.     retval = PyThread_acquire_lock( beos_dyn_lock, 1 );
  134. #endif
  135.  
  136.     /* If there's already an object with this key in the dictionary,
  137.      * we're doing a reload(), so let's nuke it.
  138.      */
  139.     py_id = PyDict_GetItemString( beos_dyn_images, name );
  140.     if( py_id ) {
  141.         beos_nuke_dyn( py_id );
  142.         retval = PyDict_DelItemString( beos_dyn_images, name );
  143.     }
  144.  
  145.     py_id = PyInt_FromLong( (long)id );
  146.     if( py_id ) {
  147.         retval = PyDict_SetItemString( beos_dyn_images, name, py_id );
  148.     }
  149.  
  150. #ifdef WITH_THREAD
  151.     PyThread_release_lock( beos_dyn_lock );
  152. #endif
  153. }
  154.  
  155.  
  156.  
  157. dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
  158.                     const char *pathname, FILE *fp)
  159. {
  160.     dl_funcptr p;
  161.     image_id the_id;
  162.     status_t retval;
  163.     char fullpath[PATH_MAX];
  164.     char funcname[258];
  165.  
  166.     if( Py_VerboseFlag ) {
  167.         printf( "load_add_on( %s )\n", pathname );
  168.     }
  169.  
  170.     /* Hmm, this old bug appears to have regenerated itself; if the
  171.      * path isn't absolute, load_add_on() will fail.  Reported to Be
  172.      * April 21, 1998.
  173.      */
  174.     if( pathname[0] != '/' ) {
  175.         (void)getcwd( fullpath, PATH_MAX );
  176.         (void)strncat( fullpath, "/", PATH_MAX );
  177.         (void)strncat( fullpath, pathname, PATH_MAX );
  178.             
  179.         if( Py_VerboseFlag ) {
  180.             printf( "load_add_on( %s )\n", fullpath );
  181.         }
  182.     } else {
  183.         (void)strcpy( fullpath, pathname );
  184.     }
  185.  
  186.     the_id = load_add_on( fullpath );
  187.     if( the_id < B_NO_ERROR ) {
  188.         /* It's too bad load_add_on() doesn't set errno or something...
  189.          */
  190.         char buff[256];  /* hate hard-coded string sizes... */
  191.  
  192.         if( Py_VerboseFlag ) {
  193.             printf( "load_add_on( %s ) failed", fullpath );
  194.         }
  195.  
  196.         switch( the_id ) {
  197.         case B_ERROR:
  198.             sprintf( buff, "BeOS: Failed to load %.200s", fullpath );
  199.             break;
  200.         default:
  201.             sprintf( buff, "Unknown error loading %.200s", fullpath );
  202.             break;
  203.         }
  204.  
  205.         PyErr_SetString( PyExc_ImportError, buff );
  206.         return NULL;
  207.     }
  208.  
  209.     sprintf(funcname, "init%.200s", shortname);
  210.     if( Py_VerboseFlag ) {
  211.         printf( "get_image_symbol( %s )\n", funcname );
  212.     }
  213.  
  214.     retval = get_image_symbol( the_id, funcname, B_SYMBOL_TYPE_TEXT, &p );
  215.     if( retval != B_NO_ERROR || p == NULL ) {
  216.         /* That's bad, we can't find that symbol in the module...
  217.          */
  218.         char buff[256];  /* hate hard-coded string sizes... */
  219.  
  220.         if( Py_VerboseFlag ) {
  221.             printf( "get_image_symbol( %s ) failed", funcname );
  222.         }
  223.  
  224.         switch( retval ) {
  225.         case B_BAD_IMAGE_ID:
  226.             sprintf( buff, "can't load init function for dynamic module: "
  227.                            "Invalid image ID for %.180s", fullpath );
  228.             break;
  229.         case B_BAD_INDEX:
  230.             sprintf( buff, "can't load init function for dynamic module: "
  231.                            "Bad index for %.180s", funcname );
  232.             break;
  233.         default:
  234.             sprintf( buff, "can't load init function for dynamic module: "
  235.                            "Unknown error looking up %.180s", funcname );
  236.             break;
  237.         }
  238.  
  239.         retval = unload_add_on( the_id );
  240.  
  241.         PyErr_SetString( PyExc_ImportError, buff );
  242.         return NULL;
  243.     }
  244.  
  245.     /* Save the module name and image ID for later so we can clean up
  246.      * gracefully.
  247.      */
  248.     beos_add_dyn( fqname, the_id );
  249.  
  250.     return p;
  251. }
  252.